package com.maikang.exammall.api;

import com.maikang.exammall.entity.Examinee;
import com.maikang.exammall.entity.User;
import com.maikang.exammall.entity.UserContext;
import com.maikang.exammall.entity.dto.FindAllRequest;
import com.maikang.exammall.entity.dto.ResponseDTO;
import com.maikang.exammall.repository.UserRepository;
import com.maikang.exammall.service.ExamineeService;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpStatus;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.server.ResponseStatusException;

import javax.validation.Valid;

import static org.apache.commons.lang3.ObjectUtils.isEmpty;
import static org.apache.commons.lang3.ObjectUtils.isNotEmpty;
import static org.apache.commons.lang3.exception.ExceptionUtils.getMessage;

@RestController
@RequiredArgsConstructor
@Log4j2
@RequestMapping("/api/examinees")
public class ExamineeController {
    private final ExamineeService service;
    private final UserRepository userRepository;

    @PostMapping(value = "/search")
    public ResponseDTO<Iterable<Examinee>> findAll(@RequestBody(required = false) FindAllRequest<Examinee> findAllRequest) {
        Iterable<Examinee> ret;
        try {
            if (findAllRequest == null || isEmpty(findAllRequest.getConditions()) && isEmpty(findAllRequest.getPageable())) {
                ret = service.findAllByUserId(UserContext.getUserId());
            } else if (isNotEmpty(findAllRequest.getPageable())) {
                ret = this.findAll(Example.of(findAllRequest.getConditions()), findAllRequest.getPageable().getPageable());
            } else {
                ret = this.findAll(Example.of(findAllRequest.getConditions()));
            }
            return ResponseDTO.ok(ret);
        } catch (Exception e) {
            throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, getMessage(e));
        }
    }

    protected Iterable<Examinee> findAll(Example<Examinee> example, Pageable pageable) {
        return service.findAll(example, pageable);
    }

    protected Iterable<Examinee> findAll(Example<Examinee> example) {
        return service.findAll(example);
    }


    public <S extends Examinee> S save(@Valid @RequestBody S entity) {
        return service.save(entity);
    }

    @PostMapping
    @Transactional(rollbackFor = Exception.class)
    public <S extends Examinee> ResponseDTO<S> wrappedSave(@Valid @RequestBody S entity) {
        entity.setUserId(UserContext.getUserId());
        // 若是本人， 则保存身份证和真实姓名到数据库.
        if (entity.getRelation() == 0) {
            User user = userRepository.findById(UserContext.getUserId()).get();
            user.setIdCardNo(entity.getIdCardNo());
            user.setRealName(entity.getExamineeName());
            userRepository.save(user);
        }
        return ResponseDTO.ok(save(entity));
    }

    @DeleteMapping("/{id}")
    public ResponseDTO deleteById(@PathVariable("id") Long id) {
        log.info("going to delete record with primary key {}", id);
        try {
            service.deleteByIdAndUserId(id, UserContext.getUserId());
            return ResponseDTO.ok();
        } catch (Exception e) {
            log.error("failed to delete: ", e);
            throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, "failed to deleteById: " + id + ", err: " + getMessage(e));
        }
    }

}
